package com.cw.jeeyt.service.impl.system;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cw.jeeyt.common.Constants;
import com.cw.jeeyt.common.enums.EnumDataJavaType;
import com.cw.jeeyt.common.enums.EnumYn;
import com.cw.jeeyt.common.utils.StringUtils;
import com.cw.jeeyt.service.bo.security.SecurityUserBo;
import com.cw.jeeyt.service.bo.system.SystemColumnInfoBo;
import com.cw.jeeyt.service.bo.system.SystemDataEntryBo;
import com.cw.jeeyt.service.bo.system.SystemDatabaseColumnBo;
import com.cw.jeeyt.service.bo.system.SystemDatabaseTableBo;
import com.cw.jeeyt.service.bo.system.SystemDictBo;
import com.cw.jeeyt.service.bo.system.SystemDictCacheBo;
import com.cw.jeeyt.service.bo.system.SystemModuleInfoBo;
import com.cw.jeeyt.service.bo.system.SystemPkInfoBo;
import com.cw.jeeyt.service.bo.system.SystemTableInfoBo;
import com.cw.jeeyt.core.util.SessionUtil;
import com.cw.jeeyt.dao.intf.system.SystemColumnInfoDao;
import com.cw.jeeyt.dao.intf.system.SystemDatabaseColumnDao;
import com.cw.jeeyt.dao.intf.system.SystemDatabaseTableDao;
import com.cw.jeeyt.dao.intf.system.SystemTableInfoDao;
import com.cw.jeeyt.dao.model.system.SystemTableInfoDo;
import com.cw.jeeyt.service.converter.system.SystemTableInfoConverter;
import com.cw.jeeyt.service.intf.system.SystemAutoCodeService;
import com.cw.jeeyt.service.intf.system.SystemColumnInfoService;
import com.cw.jeeyt.service.intf.system.SystemDataEntryService;
import com.cw.jeeyt.service.intf.system.SystemDatabaseColumnService;
import com.cw.jeeyt.service.intf.system.SystemDatabaseTableService;
import com.cw.jeeyt.service.intf.system.SystemDictService;
import com.cw.jeeyt.service.intf.system.SystemModuleInfoService;
import com.cw.jeeyt.service.intf.system.SystemTableInfoService;
import com.cw.lang.common.utils.CollectionUtil;
import com.cw.lang.mybatis.dto.PageInfo;
import com.cw.lang.common.utils.SequenceTool;
import com.cw.frame.codegen.Configuration;
import com.cw.frame.codegen.parameter.ParamHelper;

/**
 * 表模型信息业务实现类
 *
 * @author chenw
* @version 1.0.0
 */
@Service
public class SystemTableInfoServiceImpl implements SystemTableInfoService {

    private static final Logger logger = LoggerFactory.getLogger(SystemTableInfoServiceImpl.class);
    @Autowired
    private SystemTableInfoDao systemTableInfoDao;// 表模型信息数据库操作接口
    @Autowired
    @Lazy
    private SystemColumnInfoService systemColumnInfoService;// 表字段信息业务实现类
    @Autowired
    private SystemAutoCodeService systemAutoCodeService;// 自动生成代码业务逻辑实现类
    @Autowired
    @Lazy
    private SystemDatabaseTableService systemDatabaseTableService;
    @Autowired
    @Lazy
    private SystemDatabaseColumnService systemDatabaseColumnService;
    @Autowired
    @Lazy
    private SystemDataEntryService systemDataEntryService;
    @Autowired
    @Lazy
    private SystemModuleInfoService systemModuleInfoService;
    @Autowired
    private SystemDictService systemDictService;
    @Autowired
    private SystemColumnInfoDao systemColumnInfoDao;
    @Autowired
    private SystemDatabaseTableDao systemDatabaseTableDao;
    @Autowired
    private SystemDatabaseColumnDao systemDatabaseColumnDao;

    /**
     * 新增SystemTableInfo
     *
     * @param systemTableInfoBo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String insertSystemTableInfo(SystemTableInfoBo systemTableInfoBo) throws Exception {
        SecurityUserBo securityUser = SessionUtil.getSessionUser();
        if (systemTableInfoBo == null) {
            logger.error("表模型信息为空");
            return "";
        }
        SystemTableInfoDo systemTableInfo = SystemTableInfoConverter.bo2Do(systemTableInfoBo);
        String id = SequenceTool.nextId();
        systemTableInfo.setId(id);
        // 创建人
        systemTableInfo.setCreateBy(securityUser.getId());
        // 创建时间
        systemTableInfo.setCreateDate(new Date());
        // 修改人
        systemTableInfo.setUpdateBy(securityUser.getId());
        // 修改时间
        systemTableInfo.setUpdateDate(new Date());
        systemTableInfoDao.insertSystemTableInfo(systemTableInfo);
        return id;
    }

    /**
     * 更新SystemTableInfo信息
     *
     * @param systemTableInfoBo
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateSystemTableInfo(SystemTableInfoBo systemTableInfoBo) throws Exception {

        if (systemTableInfoBo == null) {
            logger.error("表模型信息为空");
            return;
        }
        SystemTableInfoDo systemTableInfo = SystemTableInfoConverter.bo2Do(systemTableInfoBo);
        // 更新人
        systemTableInfo.setUpdateBy(SessionUtil.getSessionUserId());
        systemTableInfo.setUpdateDate(new Date());
        systemTableInfoDao.updateSystemTableInfo(systemTableInfo);
    }

    /**
     * 更新表模型中的主键id
     *
     * @param tableId 表模型id
     * @param pkId 表模型主键id
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updatePkId(String tableId, Long pkId, String columnType) {

        if (null == pkId) {
            logger.error("表模型主键id信息为空");
            return;
        }
        if (StringUtils.isEmpty(tableId)) {
            logger.error("表模型id信息为空");
            return;
        }
        systemTableInfoDao.updatePkId(tableId, pkId, columnType);
    }

    /**
     * 删除SystemTableInfo
     *
     * @param systemTableInfoBo
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteSystemTableInfo(SystemTableInfoBo systemTableInfoBo) throws Exception {
        if (systemTableInfoBo == null) {
            logger.error("表模型信息为空");
            return;
        }
        SystemTableInfoDo systemTableInfo = SystemTableInfoConverter.bo2Do(systemTableInfoBo);
        String tableId = systemTableInfo.getId();
        systemTableInfoDao.deleteSystemTableInfo(systemTableInfo);
        systemColumnInfoService.deleteByTableId(tableId);
    }

    /**
     * 分页查询SystemTableInfo
     *
     * @param systemTableInfoBo
     * @param startNum
     * @param pageSize
     * @return
     * @throws Exception
     */
    @Override
    public PageInfo<SystemTableInfoBo> queryByPage(SystemTableInfoBo systemTableInfoBo, Integer startNum,
        Integer pageSize) throws Exception {

        PageInfo<SystemTableInfoDo> pageInfo = systemTableInfoDao.queryByPage(
            SystemTableInfoConverter.bo2Do(systemTableInfoBo), startNum, pageSize);
        PageInfo<SystemTableInfoBo> pageResult = new PageInfo<>(pageInfo,
            SystemTableInfoConverter.doList2BoList(pageInfo.getList()));
        if (CollectionUtil.isNotEmpty(pageResult.getList())) {
            for (SystemTableInfoBo systemTableInfo : pageResult.getList()) {
                // 循环加载表主键
                List<SystemColumnInfoBo> pkSystemColumnInfoList
                    = systemColumnInfoService.queryPkColumnInfoListByTableId(systemTableInfo.getId());
                StringBuilder pkIds = new StringBuilder("");
                if (pkSystemColumnInfoList != null && !pkSystemColumnInfoList.isEmpty()) {
                    int i = 0;
                    for (SystemColumnInfoBo scl : pkSystemColumnInfoList) {
                        if (EnumYn.Y.getCode()
                            .equals(scl.getIsPk())) {
                            if (i == 0) {
                                pkIds.append(scl.getColumnSqlCode());
                            } else {
                                pkIds.append("," + scl.getColumnSqlCode());
                            }
                        }
                        i++;
                    }
                }
                systemTableInfo.setPkId(pkIds.toString());
            }
        }
        return pageResult;
    }

    /**
     * 根据主键查询SystemTableInfo信息
     *
     * @param id
     * @return
     */
    @Override
    public SystemTableInfoBo getSystemTableInfoById(String id) throws Exception {

        SystemTableInfoBo systemTableInfoBo = SystemTableInfoConverter.do2Bo(
            systemTableInfoDao.getSystemTableInfoById(id));
        // 循环加载表主键
        List<SystemColumnInfoBo> pkSystemColumnInfoList = systemColumnInfoService.queryPkColumnInfoListByTableId(id);
        List<SystemPkInfoBo> pkInfoList = new ArrayList<>();
        if (pkSystemColumnInfoList != null && !pkSystemColumnInfoList.isEmpty()) {
            for (SystemColumnInfoBo scl : pkSystemColumnInfoList) {
                SystemPkInfoBo systemPkInfo = new SystemPkInfoBo();
                systemPkInfo.setPkId(scl.getColumnSqlCode());
                systemPkInfo.setPkIdDataType(EnumDataJavaType.find(scl.getColumnType())
                    .getValue());
                String pkIdClass = scl.getColumnCode();
                systemPkInfo.setPkIdClass(pkIdClass);
                systemPkInfo.setPkIdUp(pkIdClass.replaceFirst(pkIdClass.substring(0, 1), pkIdClass.substring(0, 1)
                    .toUpperCase()));
                systemPkInfo.setTablePkName(scl.getColumnSqlCode());
                systemPkInfo.setPkIdCnName(scl.getColumnName());
                pkInfoList.add(systemPkInfo);
            }
        }
        systemTableInfoBo.setPkInfoList(pkInfoList);
        //循环加载数据字典
        List<SystemColumnInfoBo> dictColumnInfoList = systemColumnInfoService.queryDictColumnInfoListByTableId(id);
        List<SystemDictCacheBo> dictList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(dictColumnInfoList)) {
            dictColumnInfoList.forEach(dictColumn -> {
                SystemDictBo systemDictBo = new SystemDictBo();
                systemDictBo.setItemName(dictColumn.getColumnName());
                systemDictBo.setItemCode(dictColumn.getDictCode());
                try {
                    dictList.add(systemDictService.getSystemDictByItemCode(dictColumn.getDictCode()));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
        systemTableInfoBo.setDictList(dictList);
        return systemTableInfoBo;
    }

    /**
     * 自动生成选中的表的代码
     *
     * @param tableIds 表id集合
     * @throws Exception
     */
    @Override
    public void generateCode(String tableIds, String moduleId, String generateType, HttpServletRequest request,
        HttpServletResponse response) throws Exception {

        if (StringUtils.isEmpty(tableIds)) {
            logger.info("-----要生成代码的表id为空-----");
            throw new Exception("要生成代码的表id为空");
        }
        if (StringUtils.isEmpty(moduleId)) {
            logger.info("-----要生成代码的表的模块为空-----");
            throw new Exception("要生成代码的表的模块为空");
        }
        if (StringUtils.isEmpty(generateType)) {
            logger.info("-----要生成代码的方式为空-----");
            throw new Exception("要生成代码的方式为空");
        }
        //校验表模型信息是否设置完整
        String[] tableIdList = tableIds.split(",");
        for (String tableId : tableIdList) {

            SystemTableInfoDo systemTableInfo = systemTableInfoDao.getSystemTableInfoById(tableId);

            //校验表模型字段是否为空
            List<SystemColumnInfoBo> systemColumnInfoList = systemColumnInfoService.queryColumnInfoListByTableId(
                tableId);
            if (systemColumnInfoList == null || systemColumnInfoList.isEmpty()) {
                logger.error("表模型：" + systemTableInfo.getTableName() + "字段信息为空");
                throw new Exception("表模型：" + systemTableInfo.getTableName() + "字段信息为空");
            }

            if (StringUtils.isEmpty(systemTableInfo.getId())) {
                logger.error("表模型：" + systemTableInfo.getTableName() + "主键没有设置");
                throw new Exception("表模型：" + systemTableInfo.getTableName() + "主键没有设置");
            }
        }
        try{
            systemAutoCodeService.generateCode(tableIds, moduleId, generateType, request, response);
        }catch (Exception ex){
            logger.info("生成代码失败:{}",ex.getMessage());
        }finally {
            Configuration.clean();
        }
    }

    /**
     * 自动生成模块下的所有表代码
     */
    @Override
    public void generateAllCode(String moduleId, String generateType, HttpServletRequest request,
        HttpServletResponse response) throws Exception {
        List<SystemTableInfoBo> systemTableInfoList = this.queryListByModuleId(moduleId);
        StringBuilder tableIds = new StringBuilder("");
        if (systemTableInfoList != null && !systemTableInfoList.isEmpty()) {
            int i = 0;
            for (SystemTableInfoBo systemTableInfo : systemTableInfoList) {
                if (i == 0) {
                    tableIds.append(systemTableInfo.getId());
                } else {
                    tableIds.append("," + systemTableInfo.getId());
                }
                i++;
            }
            this.generateCode(tableIds.toString(), moduleId, generateType, request, response);
        }
    }

    /**
     * 同步数据库信息到表模型信息、表模型字段信息
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importDatabaseTableInfo(String tableIds, String moduleId) throws Exception {
        //1.将数据库表信息同步到表模型信息
        //2.将数据库表字段信息同步到表模型字段信息中
        String[] tableIdList = tableIds.split(",");
        if (tableIdList != null && tableIdList.length > 0) {
            for (String tableId : tableIdList) {
                SystemDatabaseTableBo systemDatabaseTable = systemDatabaseTableService.getSystemDatabaseTableById(
                    tableId);
                SystemTableInfoBo systemTableInfoBo = new SystemTableInfoBo();
                systemTableInfoBo.setModuleId(moduleId);
                systemTableInfoBo.setTableCode(systemDatabaseTable.getTableCode());
                systemTableInfoBo.setTableCodeMapping(systemDatabaseTable.getTableCode());
                systemTableInfoBo.setTableName(systemDatabaseTable.getTableName());
                systemTableInfoBo.setTableEntityCode(
                    ParamHelper.getTableEntityCode(systemDatabaseTable.getTableCode()));
                systemTableInfoBo.setTableEntityCodeMapping(
                    ParamHelper.getTableEntityCode(systemDatabaseTable.getTableCode()));
                String returnTableId = this.insertSystemTableInfo(systemTableInfoBo);
                List<SystemDatabaseColumnBo> systemDatabaseColumnList
                    = systemDatabaseColumnService.queryColumnListByTableId(systemDatabaseTable.getId());
                List<SystemColumnInfoBo> systemColumnInfoList = new ArrayList<SystemColumnInfoBo>();
                List<SystemDataEntryBo> systemDataEntryList = new ArrayList<SystemDataEntryBo>();
                if (systemDatabaseColumnList != null && !systemDatabaseColumnList.isEmpty()) {
                    for (SystemDatabaseColumnBo systemDatabaseColumn : systemDatabaseColumnList) {
                        SystemColumnInfoBo systemColumnInfo = new SystemColumnInfoBo();
                        systemColumnInfo.setTableId(returnTableId);
                        String columnSqlCode = systemDatabaseColumn.getColumnCode();
                        String columnSqlName = systemDatabaseColumn.getColumnName();
                        systemColumnInfo.setColumnCode(ParamHelper.getFieldName(columnSqlCode));// 表模型字段编码
                        systemColumnInfo.setColumnName(columnSqlName);// 表模型字段名称
                        systemColumnInfo.setColumnSqlType(systemDatabaseColumn.getColumnType());// 数据库字段类型
                        systemColumnInfo.setColumnPoint(systemDatabaseColumn.getColumnPoint());// 数据库字段小数点
                        systemColumnInfo.setColumnLength(systemDatabaseColumn.getColumnLength());//数据库字段长度
                        systemColumnInfo.setColumnComment(systemDatabaseColumn.getColumnComment());// 数据库字段备注
                        systemColumnInfo.setColumnSqlCode(columnSqlCode);
                        systemColumnInfo.setColumnType(
                            ParamHelper.convertSqlTypeToJavaType(systemDatabaseColumn.getColumnType()));
                        String isPrimaryKey = systemDatabaseColumn.getIsPrimaryKey();
                        systemColumnInfo.setIsPk(EnumYn.N.getCode());
                        if (Constants.IS_PRIMARY_KEY.equals(isPrimaryKey)) {
                            systemColumnInfo.setIsPk(EnumYn.Y.getCode());
                        }
                        if (!"create_by".equals(columnSqlCode) && !"create_date".equals(columnSqlCode)
                            && !"update_by".equals(columnSqlCode) && !"update_date".equals(columnSqlCode)
                            && !"create_time".equals(columnSqlCode) && !"update_time".equals(columnSqlCode)
                            && !"create_time_stamp".equals(columnSqlCode) && !"create_time_stamp".equals(columnSqlCode)
                            && !"dr".equals(columnSqlCode)
                            && !"create_person".equals(columnSqlCode) && !"update_person".equals(columnSqlCode)) {
                            systemColumnInfo.setIsListColumn(EnumYn.Y.getCode());
                            systemColumnInfo.setIsFormColumn(EnumYn.Y.getCode());
                            systemColumnInfo.setIsQueryColumn(EnumYn.Y.getCode());
                        }
                        systemColumnInfo.setIsRequired(EnumYn.Y.getCode());
                        //保存到数据条目信息中
                        SystemDataEntryBo chkSystemDataEntry = new SystemDataEntryBo();
                        chkSystemDataEntry.setDataCode(columnSqlCode);
                        chkSystemDataEntry.setDataType(systemDatabaseColumn.getColumnType());
                        if (!systemDataEntryService.checkSystemDataEntry(chkSystemDataEntry)) {
                            SystemModuleInfoBo systemModuleInfo = systemModuleInfoService.getSystemModuleInfoById(
                                moduleId);
                            SystemDataEntryBo systemDataEntry = new SystemDataEntryBo();
                            systemDataEntry.setProjectId(systemModuleInfo.getProjectId());
                            systemDataEntry.setDataCode(columnSqlCode);
                            systemDataEntry.setDataName(columnSqlName);
                            systemDataEntry.setDataType(systemDatabaseColumn.getColumnType());
                            systemDataEntry.setDataJavaCode(ParamHelper.getFieldName(columnSqlCode));
                            systemDataEntry.setDataJavaType(
                                ParamHelper.convertSqlTypeToJavaType(systemDatabaseColumn.getColumnType()));
                            systemDataEntry.setDataLength(systemDatabaseColumn.getColumnLength());
                            systemDataEntry.setDataPoint(systemDatabaseColumn.getColumnPoint());
                            systemDataEntry.setDataComment(systemDatabaseColumn.getColumnComment());
                            systemDataEntryList.add(systemDataEntry);
                        }
                        systemColumnInfoList.add(systemColumnInfo);
                    }
                    //批量新增列
                    systemColumnInfoService.insertSystemColumnInfoBat(systemColumnInfoList);
                    //批量新增数据条目
                    systemDataEntryService.insertSystemDataEntryBat(systemDataEntryList);
                }
            }
        }
    }

    /**
     * 查询模块下的表信息
     */
    @Override
    public List<SystemTableInfoBo> queryListByModuleId(String moduleId) throws Exception {
        if (StringUtils.isEmpty(moduleId)) {
            logger.equals("模块id不能为空");
            return null;
        }
        return SystemTableInfoConverter.doList2BoList(systemTableInfoDao.queryListByModuleId(moduleId));
    }

    /**
     * 查询所有表信息
     */
    @Override
    public List<SystemTableInfoBo> querySystemTableInfoList() throws Exception {

        return SystemTableInfoConverter.doList2BoList(systemTableInfoDao.querySystemTableInfoList());
    }

    /**
     * 清空模块对应数据库信息
     *
     * @param moduleId 模块编号
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean clearDatabaseInfo(String moduleId) throws Exception {
        SystemModuleInfoBo systemModuleInfoBo = systemModuleInfoService.getSystemModuleInfoById(moduleId);
        // systemColumnListDao.deleteByTableCodePrefix(systemModuleInfoBo.getModuleCode(),
        //     systemModuleInfoBo.getModulePrefix());
        systemColumnInfoDao.deleteByTableCodePrefix(systemModuleInfoBo.getModuleCode(),
            systemModuleInfoBo.getModulePrefix());
        // systemColumnQueryDao.deleteByTableCodePrefix(systemModuleInfoBo.getModuleCode(),
        //     systemModuleInfoBo.getModulePrefix());
        // systemColumnOrderDao.deleteByTableCodePrefix(systemModuleInfoBo.getModuleCode(),
        //     systemModuleInfoBo.getModulePrefix());
        systemTableInfoDao.deleteByTableCodePrefix(systemModuleInfoBo.getModuleCode(),
            systemModuleInfoBo.getModulePrefix());
        systemDatabaseColumnDao.deleteByTableCodePrefix(systemModuleInfoBo.getModuleCode(),
            systemModuleInfoBo.getModulePrefix());
        systemDatabaseTableDao.deleteByTableCodePrefix(systemModuleInfoBo.getModuleCode(),
            systemModuleInfoBo.getModulePrefix());
        return true;
    }
}
